# -*- mode: python; coding: utf-8; -*-
##--------------------------------------------------------------------------##
##
## Copyright (C) 1998-2003 Markus Oberhumer <markus@oberhumer.com>
## Copyright (C) 2003 Mt. Hood Playing Card Co.
## Copyright (C) 2005-2010 Skomoroh <skomoroh@users.sourceforge.net>
## Copyright (C) 2010-2013 Jeremy Austin-Bardo <tjaustinbardo@gmail.com>
##
## This program is free software: you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program.  If not, see <http://www.gnu.org/licenses/>.
##
##--------------------------------------------------------------------------##
__docformat__ = 'restructuredtext en'

from ... import hint
from ... import formlib as layout
from ... import pilelib as stack
from ...gamelib import info as gi
from ...packlib import info as cs, place
from ...piles import hexadeck as xstack
from ...utillib.misc import kwdefault
from .. import klondike

GT, SL = gi.GT, gi.SL
Wrap = stack.StackWrapper


class HexAKlon(cs.HexA_Deck, klondike.Klondike):
    """
    Finish 1 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [5 N, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=INFINITE)

        Deal 1 card per `s.waste` on click. Unlimited redeals.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation,
          pysollib.stacks.hexadeck.TrumpFoundation (mod=4, max_move=0,
          base_rank=ANY)

        W 4 :: Build up in rank by same suit. Play top.

        E 1 :: Build up any with trump. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack

        Init 1..8 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x24a96, name='Hex A Klon', category=cs.TYPE_HEXADECK,
                    game_type=GT.KLONDIKE, decks=1, redeals=cs.INFINITE,
                    skill_level=SL.BALANCED, versiom='4.20')
    __author__ = 'Markus Oberhumer'
    __version__ = 7.70

    _foundations_ = (stack.SS_Foundation,
                    Wrap(xstack.TrumpFoundation, mod=4, max_move=0,
                         base_rank=cs.ANY))
    _row_ = xstack.TW_AC_RowStack
    _hint_ = hint.CautiousDefaultHint

    def _create_game(self, rows=8, playcards=20, **kw):
        l, s = self._layout_(self), self.s
        kwdefault(kw, rows=8, playcards=20)
        l.create(**kw)
        self.table_size = l.size
        s['talon'] = self._talon_(l.s['talon'].x, l.s['talon'].y, game=self)
        s['wastes'] = [self._waste_(p.x, p.y, game=self) for p in l.s['wastes']]
        s['foundations'] = [self._foundations_[int(p.suit == l.SUIT[-1])](p.x,
                       p.y, game=self, suit=p.suit) for p in l.s['foundations']]
        s['rows'] = [self._row_(p.x, p.y, self) for p in l.s['rows']]
        l.defaultAll()
        return l


class HexAKlonByThrees(HexAKlon):
    """
    Finish 1 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [5 N, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=INFINITE, num_deal=3)

        Deal 3 card per `s.waste` on click. Unlimited redeals.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 3 card. Build none. Play top.

      _foundations_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation,
          pysollib.stacks.hexadeck.TrumpFoundation (mod=4, max_move=0,
          base_rank=ANY)

        W 4 :: Build up in rank by same suit. Play top.

        E 1 :: Build up any with trump. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack

        Init 1..8 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x263fb, name='Hex A Klon by Threes',
                    category=cs.TYPE_HEXADECK, game_type=GT.KLONDIKE, decks=1,
                    redeals=cs.INFINITE, skill_level=SL.BALANCED,
                    version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=cs.INFINITE, num_deal=3)


class KingOnlyHexAKlon(HexAKlon):
    """
    Finish 1 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [5 N, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=INFINITE)

        Deal 1 card per `s.waste` on click. Unlimited redeals.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundations_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation,
          pysollib.stacks.hexadeck.TrumpFoundation (mod=4, max_move=0,
          base_rank=ANY)

        W 4 :: Build up in rank by same suit. Play top.

        E 1 :: Build up any with trump. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 1..8 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank. Base 0x10.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x263fc, name='King Only Hex A Klon',
                    category=cs.TYPE_HEXADECK, game_type=GT.KLONDIKE, decks=1,
                    redeals=cs.INFINITE, skill_level=SL.BALANCED,
                    version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _row_ = Wrap(xstack.TW_AC_RowStack, base_rank=cs.x10)

    def _pile_place(self, cards):
        """
        _pile_place(cards) -> tuple

        Get a new copy of cards and shuffle. Place any 1 trump on top.

        :returns: deck of cards shuffle and placed.
        :seealso: `game.shuffle` for keyword details.
        """
        return place.MoveToTop(cards, lambda c: place.move(c,
                                                    suits=[len(self['suits'])]))


class KlondikePlus16(cs.HexA_Deck, klondike.Klondike):
    """
    Finish 1 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [5 N, no offset, no trump]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=2)

        Deal 1 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundations_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation,
          pysollib.stacks.hexadeck..TrumpFoundation (mod=4, max_move=0,
          base_rank=ANY)

        Build up in rank by same suit. Play top. No trump.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 1..8 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank. Base 0x10.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x263fa, name='Klondike +16',
                    category=cs.TYPE_HEXADECK, game_type=GT.KLONDIKE, decks=1,
                    redeals=1, skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=2)
    _row_ = Wrap(xstack.TW_AC_RowStack, base_rank=cs.x10)

    def _create_game(self, **kw):
        kwdefault(kw, rows=8, playcards=20)
        return super(KlondikePlus16)._create_game(**kw)


class TheFamiliar(KlondikePlus16):
    """
    Finish 1 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [5 N, no offset, no trump]
        - reserve [1 S, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=2)

        Deal 1 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation

        Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 1..8 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank. Base 0x10.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TrumpReserve

        Build any trump. Play top. Max 3 cards

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x263fd, name='The Familiar',
                    category=cs.TYPE_HEXADECK, game_type=GT.KLONDIKE, decks=1,
                    redeals=1, skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _reserve_ = xstack.TrumpReserve

    def _create_game(self, **kw):
        kw.setdefault('reserves', 1)
        return super(TheFamiliar, self)._create_game(self, **kw)


class TwoFamiliars(TheFamiliar):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [8 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [10 N, no offset, no trump]
        - reserve [1 S, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=2)

        Deal 1 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation

        Build up in rank by same suit. Play top.. No trump.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 1..8 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank. Base 0x10.

      _reserve_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TrumpReserve

        Build any trump. Play top. Max 3 cards

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x263fe, name='Two Familiars',
                    category=cs.TYPE_HEXADECK, game_type=GT.KLONDIKE, decks=2,
                    redeals=1, skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70


class Drawbridge(cs.HexA_Deck, klondike.Klondike):
    """
    Finish 1 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layout.HarpLayout

        - row [8 horz N foundation, vert offset]
        - talon [1 SE, no offset]
        - waste [1 W talon, no offset]
        - foundation [10 S, no offset, no trump]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=2)

        Deal 1 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation

        W 4 :: Build up in rank by same suit. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 1..7 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x26400, name='Drawbridge', category=cs.TYPE_HEXADECK,
                    game_type=GT.KLONDIKE, decks=1, redeals=1,
                    skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _layout_ = layout.HarpLayout
    _talon_ = Wrap(stack.WasteTalon, max_rounds=2)
    _row_ = xstack.TW_AC_RowStack
    _hint_ = hint.CautiousDefaultHint

    def _create_game(self, **kw):
        kwdefault(kw, rows=7, playcards=20)
        return super(Drawbridge, self)._create_game(self, **kw)


class DoubleDrawbridge(Drawbridge):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layout.HarpLayout

        - row [10 horz N foundation, vert offset]
        - talon [1 SE, no offset]
        - waste [1 W talon, no offset]
        - foundation [10 S, no offset, no trump]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=2)

        Deal 1 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation

        W 4 :: Build up in rank by same suit. Play top.

        E 1 :: Build up any with trump. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 1..10 card. Build down in rank by alt color with trump wild.
        Play seq with trump in rank.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x26401, name='Double Drawbridge',
                    category=cs.TYPE_HEXADECK, game_type=GT.KLONDIKE, decks=2,
                    redeals=1, skill_level=SL.BALANCED, version='0.50fc',
                    altnames=('Drawbridge (2 Decks)',))
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    def _create_game(self, **kw):
        kwdefault(kw, rows=10, playcards=20)
        return super(DoubleDrawbridge, self)._create_game(self, **kw)


class CluitjarsLair(HexAKlon):
    """
    Finish 2 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [7 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [5 N, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=2)

        Deal 1 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation

        W 4 :: Build up in rank by same suit. Play top.

        E 1 :: Build up any with trump. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 3 card. Build down in rank by alt color. Play seq.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x26403, name='Cluitjarʼs Lair',
                    category=cs.TYPE_HEXADECK, game_type=GT.HEXADECK, decks=1,
                    skill_level=SL.BALANCED, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _talon_ = Wrap(stack.WasteTalon, max_rounds=2)
    _row_ = xstack.TR_AC_RowStack

    def _create_game(self, **kw):
        kwdefault(kw, rows=7, playcards=20)
        return super(HiddenPassages, self)._create_game(**kw)

    def _start(self, rows=3, flip=False, **kw):
        self.s['talon'].dealBaseCards(ncards=4)
        for i in range(rows - 1):
            self.s['talon'].dealRow(flip=flip, frames=0)
        self._play_sound('deal')
        self.s['talon'].dealRow()
        self.s['talon'].deal_cards()


class HiddenPassages(CluitjarsLair):
    """
    Finish 1 deck on _foundation_.

    :CVariables:
      _layout_ : pysollib.layout.Layout
        .. pysollib.layouts.klondike.KlondikeLayout

        - row [7 horz S foundation, vert offset]
        - talon [1 NW, no offset]
        - waste [1 E talon, no offset]
        - foundation [5 N, no offset]

      _talon_ : pysollib.stack.Stack
        .. pysollib.stack.WasteTalon (max_rounds=2)

        Deal 1 card per `s.waste` on click. 1 redeal.

      _waste_ : pysollib.stack.Stack
        .. pysollib.stack.WasteStack

        Init 1 card. Build none. Play top.

      _foundation_ : pysollib.stack.Stack
        .. pysollib.stack.SS_Foundation

        W 4 :: Init base Ace. Build up in rank by same suit. Play top.

        E 1 :: Build up any with trump. Play top.

      _row_ : pysollib.stack.Stack
        .. pysollib.stacks.hexadeck.TW_AC_RowStack (base_rank=x10)

        Init 3 card. Build down in rank by alt color with trump wild. Play
        seq with trump in rank.

      _hint_ : pysollib.hint.AbstractHint
        .. pysollib.hint.CautiousDefaultHint
    """
    __info__ = dict(id=0x26402, name='Hidden Passages',
                    category=cs.TYPE_HEXADECK, game_type=GT.KLONDIKE, decks=1,
                    redeals=1, skill_level=SL.MOSTLY_LUCK, version='0.50fc')
    __author__ = 'Mt. Hood Playing Card'
    __version__ = 7.70

    _row_ = xstack.TR_AC_RowStack

    def _pile_place(self, cards):
        """
        _pile_place(cards) -> tuple

        Get a new copy of cards and shuffle. Place any 1 rank set not trump
        on top by deck, suit and rank.

        :returns: deck of cards shuffle and placed.
        :seealso: `game.shuffle` for keyword details.
        """
        return place.MoveToTop(cards, lambda c: place.AllAce(c,
                                                           suits=self['suits']))


PROVIDES = [CluitjarsLair, Drawbridge, DoubleDrawbridge, HexAKlon,
            HexAKlonByThrees, KingOnlyHexAKlon, KlondikePlus16, TheFamiliar,
            TwoFamiliars]